namespace Specifications.Extensions
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Reflection;

    public class AllPropertiesAssertion<T> : PropertyAssertion<T> where T : class, INotifyPropertyChanged
    {
        private readonly IList<PropertyInfo> ignored = new List<PropertyInfo>();

        public AllPropertiesAssertion(INotifyPropertyChanged propertyOwner) : base(propertyOwner)
        {
        }

        public AllPropertiesAssertion<T> Ignoring<K>(Expression<Func<K>> property)
        {
            ignored.Add(property.GetPropertyInfo());
            return this;
        }

        protected override IEnumerable<PropertyInfo> GetCandidateProperties()
        {
            return from property in typeof (T).GetProperties()
                   where !ignored.Contains(property)
                         && property.CanWrite
                   select property;
        }

        public AllPropertiesAssertion<T> SetValue<K>(Expression<Func<K>> property, K valueToSet)
        {
            setValues[property.GetPropertyInfo()] = valueToSet;
            return this;
        }

        public void RaiseChangeNotifcation()
        {
            Execute();
        }
    }
}